package net.zoneland.knowledge.utils;

import net.zoneland.knowledge.enums.VisitTypeEnum;
import net.zoneland.oplog.api.OpLog;
import net.zoneland.oplog.api.OpLogHelper;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.nio.ByteBuffer;
import java.util.UUID;

/**
 * 操作日志工具类.
 * @author zmq
 * 2022/3/10 14:09
 */
public final class OplogUtils {
    /**
     * 系统名称.
     */
    private static final String SYSTEMR = "党建智能机器人";

    /**
     * 项目名称.
     */
    private static final String PROJECT_NAME = "查询服务后端";

    /**
     * 项目编码.
     */
    private static final String PROJECT_CODE = "oadz-robot-search";

    /**
     * byte数组长度.
     */
    private static final int BYTE_LENGTH = 16;

    /**
     * 私有构造.
     */
    private OplogUtils() {

    }
    /**
     * 发送操作日志.
     * @param request http日志
     * @param opLog 业务日志对象
     */
    public static void sendOpLog(final HttpServletRequest request, final OpLogBean opLog) {
        if (opLog != null) {
            OpLog oplog = OpLogHelper.getOpLog();
            oplog.initQuery(request).setQueryResult(Boolean.TRUE).setSystem(SYSTEMR).setSystemRef(SYSTEMR).setIMEI("无")
                .setInterfacename(PROJECT_CODE);
            oplog.setOpTime(System.currentTimeMillis()).setOpType(opLog.getRequestUri())
                .setFormType(opLog.getMethod())
                .setModule(PROJECT_CODE).setTerminalType(getTerminalType(request));
            oplog.setElapsedTime(opLog.getConsumerTime());
            String exceptionMsg = opLog.getExceptionMsg();
            if (StringUtils.isNotBlank(exceptionMsg)) {
                oplog.setQueryResult(Boolean.FALSE).setErrorCode("500");
                oplog.putExtraEntry("exceptionMsg", replaceSeparator(exceptionMsg));
            }
            oplog.putExtraEntry("requestUri", replaceSeparator(opLog.getRequestUri()));
            oplog.putExtraEntry("queryStr", replaceSeparator(opLog.getQueryStr()));
            oplog.putExtraEntry("reqeustMsg", replaceSeparator(opLog.getRequestArgs()));
            oplog.putExtraEntry("token", replaceSeparator(opLog.getToken()));
            oplog.putExtraEntry("responseMsg", replaceSeparator(opLog.getReturnJson()));
            oplog.putExtraEntry("projectCode", PROJECT_CODE);
            oplog.putExtraEntry("projectName", PROJECT_NAME);
            oplog.putExtraEntry("consumerTime", opLog.getConsumerTime() + "ms");
            oplog.putExtraEntry("methodCode", replaceSeparator(opLog.getMethod()));
            oplog.setUserId(opLog.getUserId());
            oplog.doLog();
            oplog.removeFromThreadLocal();
        }
    }

    /**
     * 获取访问终端类型.
     * @param request http请求
     * @return 访问终端类型
     */
    private static String getTerminalType(final HttpServletRequest request) {
        String visitType = request.getHeader("visit_type");
        VisitTypeEnum type = VisitTypeEnum.MOA;
        if (StringUtils.isNotBlank(visitType)) {
            type = VisitTypeEnum.getByValue(visitType);
        }
        return type == VisitTypeEnum.MOA ? "Mobile" : "PC";
    }

    /**
     * 构造uuid.
     * @return uuid
     */
    private static String shortUUID128() {
        UUID uuid = UUID.randomUUID();
        ByteBuffer buf = ByteBuffer.wrap(new byte[BYTE_LENGTH]);
        buf.putLong(uuid.getMostSignificantBits());
        buf.putLong(uuid.getLeastSignificantBits());
        return Base64.encodeBase64URLSafeString(buf.array());
    }

    /**
     * 替换关键字.
     * @param str 字符串
     * @return 替换结果
     */
    private static String replaceSeparator(final String str) {
        if (StringUtils.isNotBlank(str)) {
            return str.replace("|", "/");
        }
        return str;
    }

    /**
     * 操作日志bean.
     */
    public static class OpLogBean {
        /**
         * 用户uid.
         */
        private String userId;
        /**
         * 方法名称.
         */
        private String method;
        /**
         * 查询参数.
         */
        private String queryStr;
        /**
         * 请求uri.
         */
        private String requestUri;
        /**
         * token.
         */
        private String token;
        /**
         * 响应结果.
         */
        private String returnJson;
        /**
         * 请求传参内容.
         */
        private String requestArgs;
        /**
         * 耗时.
         */
        private long consumerTime;
        /**
         * 异常信息.
         */
        private String exceptionMsg;
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getUserId() {
            return userId;
        }
        /**
         * 设置 属性值.
         * @param userId 属性值
         * @return 当前对象
         */
        public OpLogBean setUserId(final String userId) {
            this.userId = userId;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getMethod() {
            return method;
        }
        /**
         * 设置 属性值.
         * @param method 属性值
         * @return 当前对象
         */
        public OpLogBean setMethod(final String method) {
            this.method = method;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getQueryStr() {
            return queryStr;
        }
        /**
         * 设置 属性值.
         * @param queryStr 属性值
         * @return 当前对象
         */
        public OpLogBean setQueryStr(final String queryStr) {
            this.queryStr = queryStr;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getRequestUri() {
            return requestUri;
        }
        /**
         * 设置 属性值.
         * @param requestUri 属性值
         * @return 当前对象
         */
        public OpLogBean setRequestUri(final String requestUri) {
            this.requestUri = requestUri;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getToken() {
            return token;
        }
        /**
         * 设置 属性值.
         * @param token 属性值
         * @return 当前对象
         */
        public OpLogBean setToken(final String token) {
            this.token = token;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getReturnJson() {
            return returnJson;
        }
        /**
         * 设置 属性值.
         * @param returnJson 属性值
         * @return 当前对象
         */
        public OpLogBean setReturnJson(final String returnJson) {
            this.returnJson = returnJson;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getRequestArgs() {
            return requestArgs;
        }
        /**
         * 设置 属性值.
         * @param requestArgs 属性值
         * @return 当前对象
         */
        public OpLogBean setRequestArgs(final String requestArgs) {
            this.requestArgs = requestArgs;
            return this;
        }
        /**
         * 获取 属性值.
         * @return 属性值
         */
        public long getConsumerTime() {
            return consumerTime;
        }
        /**
         * 设置 属性值.
         * @param consumerTime 属性值
         * @return 当前对象
         */
        public OpLogBean setConsumerTime(final long consumerTime) {
            this.consumerTime = consumerTime;
            return this;
        }

        /**
         * 获取 属性值.
         * @return 属性值
         */
        public String getExceptionMsg() {
            return exceptionMsg;
        }

        /**
         * 设置 属性值.
         * @param exceptionMsg 属性值
         * @return 当前对象
         */
        public OpLogBean setExceptionMsg(final String exceptionMsg) {
            this.exceptionMsg = exceptionMsg;
            return this;
        }
    }

    /**
     * 构造32位的uuid.
     * @return
     */
    public static String getUuid32(){
        return UUID.randomUUID().toString().replace("-","");
    }

}
